{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n",
    "- Author: Sebastian Raschka\n",
    "- GitHub Repository: https://github.com/rasbt/deeplearning-models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sebastian Raschka \n",
      "\n",
      "CPython 3.6.8\n",
      "IPython 7.2.0\n",
      "\n",
      "torch 1.0.0\n"
     ]
    }
   ],
   "source": [
    "%load_ext watermark\n",
    "%watermark -a 'Sebastian Raschka' -v -p torch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Model Zoo -- Multilayer Perceptron From Scratch (Sigmoid activation, MSE Loss)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Implementation of a 1-hidden layer multi-layer perceptron from scratch using\n",
    "- sigmoid activation in the hidden layer\n",
    "- sigmoid activation in the output layer\n",
    "- Mean Squared Error loss function"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "import torch\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "import numpy as np\n",
    "from torchvision import datasets\n",
    "from torchvision import transforms\n",
    "from torch.utils.data import DataLoader\n",
    "import torch.nn.functional as F\n",
    "import torch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Settings and Dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image batch dimensions: torch.Size([100, 1, 28, 28])\n",
      "Image label dimensions: torch.Size([100])\n"
     ]
    }
   ],
   "source": [
    "##########################\n",
    "### SETTINGS\n",
    "##########################\n",
    "\n",
    "RANDOM_SEED = 1\n",
    "BATCH_SIZE = 100\n",
    "NUM_EPOCHS = 50\n",
    "\n",
    "##########################\n",
    "### MNIST DATASET\n",
    "##########################\n",
    "\n",
    "# Note transforms.ToTensor() scales input images\n",
    "# to 0-1 range\n",
    "train_dataset = datasets.MNIST(root='data', \n",
    "                               train=True, \n",
    "                               transform=transforms.ToTensor(),\n",
    "                               download=True)\n",
    "\n",
    "test_dataset = datasets.MNIST(root='data', \n",
    "                              train=False, \n",
    "                              transform=transforms.ToTensor())\n",
    "\n",
    "\n",
    "train_loader = DataLoader(dataset=train_dataset, \n",
    "                          batch_size=BATCH_SIZE, \n",
    "                          shuffle=True)\n",
    "\n",
    "test_loader = DataLoader(dataset=test_dataset, \n",
    "                         batch_size=BATCH_SIZE, \n",
    "                         shuffle=False)\n",
    "\n",
    "# Checking the dataset\n",
    "for images, labels in train_loader:  \n",
    "    print('Image batch dimensions:', images.shape)\n",
    "    print('Image label dimensions:', labels.shape)\n",
    "    break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Model Implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "##########################\n",
    "### MODEL\n",
    "##########################\n",
    "\n",
    "class MultilayerPerceptron():\n",
    "\n",
    "    def __init__(self, num_features, num_hidden, num_classes):\n",
    "        super(MultilayerPerceptron, self).__init__()\n",
    "        \n",
    "        self.num_classes = num_classes\n",
    "        \n",
    "        # hidden 1\n",
    "        self.weight_1 = torch.zeros(num_hidden, num_features, \n",
    "                                    dtype=torch.float).normal_(0.0, 0.1)\n",
    "        self.bias_1 = torch.zeros(num_hidden, dtype=torch.float)\n",
    "        \n",
    "        # output\n",
    "        self.weight_o = torch.zeros(self.num_classes, num_hidden, \n",
    "                                    dtype=torch.float).normal_(0.0, 0.1)\n",
    "        self.bias_o = torch.zeros(self.num_classes, dtype=torch.float)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        # hidden 1\n",
    "        \n",
    "        # input dim: [n_hidden, n_features] dot [n_features, n_examples] .T\n",
    "        # output dim: [n_examples, n_hidden]\n",
    "        z_1 = torch.mm(x, self.weight_1.t()) + self.bias_1\n",
    "        a_1 = torch.sigmoid(z_1)\n",
    "\n",
    "        # hidden 2\n",
    "        # input dim: [n_classes, n_hidden] dot [n_hidden, n_examples] .T\n",
    "        # output dim: [n_examples, n_classes]\n",
    "        z_2 = torch.mm(a_1, self.weight_o.t()) + self.bias_o\n",
    "        a_2 = torch.sigmoid(z_2)\n",
    "        return a_1, a_2\n",
    "\n",
    "    def backward(self, x, a_1, a_2, y):  \n",
    "    \n",
    "        #########################\n",
    "        ### Output layer weights\n",
    "        #########################\n",
    "        \n",
    "        # onehot encoding\n",
    "        y_onehot = torch.FloatTensor(y.size(0), self.num_classes)\n",
    "        y_onehot.zero_()\n",
    "        y_onehot.scatter_(1, y.view(-1, 1).long(), 1)\n",
    "        \n",
    "\n",
    "        # Part 1: dLoss/dOutWeights\n",
    "        ## = dLoss/dOutAct * dOutAct/dOutNet * dOutNet/dOutWeight\n",
    "        ## where DeltaOut = dLoss/dOutAct * dOutAct/dOutNet\n",
    "        ## for convenient re-use\n",
    "        \n",
    "        # input/output dim: [n_examples, n_classes]\n",
    "        dloss_da2 = 2.*(a_2 - y_onehot) / y.size(0)\n",
    "\n",
    "        # input/output dim: [n_examples, n_classes]\n",
    "        da2_dz2 = a_2 * (1. - a_2) # sigmoid derivative\n",
    "\n",
    "        # output dim: [n_examples, n_classes]\n",
    "        delta_out = dloss_da2 * da2_dz2 # \"delta (rule) placeholder\"\n",
    "\n",
    "        # gradient for output weights\n",
    "        \n",
    "        # [n_examples, n_hidden]\n",
    "        dz2__dw_out = a_1\n",
    "        \n",
    "        # input dim: [n_classlabels, n_examples] dot [n_examples, n_hidden]\n",
    "        # output dim: [n_classlabels, n_hidden]\n",
    "        dloss__dw_out = torch.mm(delta_out.t(), dz2__dw_out)\n",
    "        dloss__db_out = torch.sum(delta_out, dim=0)\n",
    "        \n",
    "\n",
    "        #################################        \n",
    "        # Part 2: dLoss/dHiddenWeights\n",
    "        ## = DeltaOut * dOutNet/dHiddenAct * dHiddenAct/dHiddenNet * dHiddenNet/dWeight\n",
    "        \n",
    "        # [n_classes, n_hidden]\n",
    "        dz2__a1 = self.weight_o\n",
    "        \n",
    "        # output dim: [n_examples, n_hidden]\n",
    "        dloss_a1 = torch.mm(delta_out, dz2__a1)\n",
    "        \n",
    "        # [n_examples, n_hidden]\n",
    "        da1__dz1 = a_1 * (1. - a_1) # sigmoid derivative\n",
    "        \n",
    "        # [n_examples, n_features]\n",
    "        dz1__dw1 = x\n",
    "        \n",
    "        # output dim: [n_hidden, n_features]\n",
    "        dloss_dw1 = torch.mm((dloss_a1 * da1__dz1).t(), dz1__dw1)\n",
    "        dloss_db1 = torch.sum((dloss_a1 * da1__dz1), dim=0)\n",
    "\n",
    "        return dloss__dw_out, dloss__db_out, dloss_dw1, dloss_db1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "####################################################\n",
    "##### Training and evaluation wrappers\n",
    "###################################################\n",
    "\n",
    "def to_onehot(y, num_classes):\n",
    "    y_onehot = torch.FloatTensor(y.size(0), num_classes)\n",
    "    y_onehot.zero_()\n",
    "    y_onehot.scatter_(1, y.view(-1, 1).long(), 1).float()\n",
    "    return y_onehot\n",
    "\n",
    "\n",
    "def loss_func(targets_onehot, probas_onehot):\n",
    "    return torch.mean(torch.mean((targets_onehot - probas_onehot)**2, dim=0))\n",
    "\n",
    "\n",
    "def compute_mse(net, data_loader):\n",
    "    curr_mse, num_examples = torch.zeros(model.num_classes).float(), 0\n",
    "    with torch.no_grad():\n",
    "        for features, targets in data_loader:\n",
    "            features = features.view(-1, 28*28)\n",
    "            logits, probas = net.forward(features)\n",
    "            y_onehot = to_onehot(targets, model.num_classes)\n",
    "            loss = torch.sum((y_onehot - probas)**2, dim=0)\n",
    "            num_examples += targets.size(0)\n",
    "            curr_mse += loss\n",
    "\n",
    "        curr_mse = torch.mean(curr_mse/num_examples, dim=0)\n",
    "        return curr_mse\n",
    "\n",
    "\n",
    "def train(model, data_loader, num_epochs,\n",
    "          learning_rate=0.1):\n",
    "    \n",
    "    minibatch_cost = []\n",
    "    epoch_cost = []\n",
    "    \n",
    "    for e in range(num_epochs):\n",
    "        \n",
    "        for batch_idx, (features, targets) in enumerate(train_loader):\n",
    "            \n",
    "            features = features.view(-1, 28*28)\n",
    "            \n",
    "            #### Compute outputs ####\n",
    "            a_1, a_2 = model.forward(features)\n",
    "\n",
    "            #### Compute gradients ####\n",
    "            dloss__dw_out, dloss__db_out, dloss_dw1, dloss_db1 = \\\n",
    "                model.backward(features, a_1, a_2, targets)\n",
    "\n",
    "            #### Update weights ####\n",
    "            model.weight_1 -= learning_rate * dloss_dw1\n",
    "            model.bias_1 -= learning_rate * dloss_db1\n",
    "            model.weight_o -= learning_rate * dloss__dw_out\n",
    "            model.bias_o -= learning_rate * dloss__db_out\n",
    "            \n",
    "            #### Logging ####\n",
    "            curr_cost = loss_func(to_onehot(targets, model.num_classes), a_2)\n",
    "            minibatch_cost.append(curr_cost)\n",
    "            if not batch_idx % 50:\n",
    "                print ('Epoch: %03d/%03d | Batch %03d/%03d | Cost: %.4f' \n",
    "                       %(e+1, NUM_EPOCHS, batch_idx, \n",
    "                         len(train_loader), curr_cost))\n",
    "        \n",
    "        #### Logging ####        \n",
    "        curr_cost = compute_mse(model, train_loader)\n",
    "        epoch_cost.append(curr_cost)\n",
    "        print('Epoch: %03d/%03d |' % (e+1, NUM_EPOCHS), end=\"\")\n",
    "        print(' Train MSE: %.5f' % curr_cost)\n",
    "\n",
    "    return minibatch_cost, epoch_cost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch: 001/050 | Batch 000/600 | Cost: 0.2471\n",
      "Epoch: 001/050 | Batch 050/600 | Cost: 0.0885\n",
      "Epoch: 001/050 | Batch 100/600 | Cost: 0.0880\n",
      "Epoch: 001/050 | Batch 150/600 | Cost: 0.0877\n",
      "Epoch: 001/050 | Batch 200/600 | Cost: 0.0847\n",
      "Epoch: 001/050 | Batch 250/600 | Cost: 0.0838\n",
      "Epoch: 001/050 | Batch 300/600 | Cost: 0.0808\n",
      "Epoch: 001/050 | Batch 350/600 | Cost: 0.0801\n",
      "Epoch: 001/050 | Batch 400/600 | Cost: 0.0766\n",
      "Epoch: 001/050 | Batch 450/600 | Cost: 0.0740\n",
      "Epoch: 001/050 | Batch 500/600 | Cost: 0.0730\n",
      "Epoch: 001/050 | Batch 550/600 | Cost: 0.0730\n",
      "Epoch: 001/050 | Train MSE: 0.06566\n",
      "Epoch: 002/050 | Batch 000/600 | Cost: 0.0644\n",
      "Epoch: 002/050 | Batch 050/600 | Cost: 0.0637\n",
      "Epoch: 002/050 | Batch 100/600 | Cost: 0.0600\n",
      "Epoch: 002/050 | Batch 150/600 | Cost: 0.0580\n",
      "Epoch: 002/050 | Batch 200/600 | Cost: 0.0541\n",
      "Epoch: 002/050 | Batch 250/600 | Cost: 0.0546\n",
      "Epoch: 002/050 | Batch 300/600 | Cost: 0.0547\n",
      "Epoch: 002/050 | Batch 350/600 | Cost: 0.0488\n",
      "Epoch: 002/050 | Batch 400/600 | Cost: 0.0515\n",
      "Epoch: 002/050 | Batch 450/600 | Cost: 0.0476\n",
      "Epoch: 002/050 | Batch 500/600 | Cost: 0.0486\n",
      "Epoch: 002/050 | Batch 550/600 | Cost: 0.0447\n",
      "Epoch: 002/050 | Train MSE: 0.04302\n",
      "Epoch: 003/050 | Batch 000/600 | Cost: 0.0413\n",
      "Epoch: 003/050 | Batch 050/600 | Cost: 0.0404\n",
      "Epoch: 003/050 | Batch 100/600 | Cost: 0.0374\n",
      "Epoch: 003/050 | Batch 150/600 | Cost: 0.0351\n",
      "Epoch: 003/050 | Batch 200/600 | Cost: 0.0374\n",
      "Epoch: 003/050 | Batch 250/600 | Cost: 0.0371\n",
      "Epoch: 003/050 | Batch 300/600 | Cost: 0.0347\n",
      "Epoch: 003/050 | Batch 350/600 | Cost: 0.0359\n",
      "Epoch: 003/050 | Batch 400/600 | Cost: 0.0373\n",
      "Epoch: 003/050 | Batch 450/600 | Cost: 0.0305\n",
      "Epoch: 003/050 | Batch 500/600 | Cost: 0.0333\n",
      "Epoch: 003/050 | Batch 550/600 | Cost: 0.0318\n",
      "Epoch: 003/050 | Train MSE: 0.03251\n",
      "Epoch: 004/050 | Batch 000/600 | Cost: 0.0292\n",
      "Epoch: 004/050 | Batch 050/600 | Cost: 0.0312\n",
      "Epoch: 004/050 | Batch 100/600 | Cost: 0.0273\n",
      "Epoch: 004/050 | Batch 150/600 | Cost: 0.0293\n",
      "Epoch: 004/050 | Batch 200/600 | Cost: 0.0293\n",
      "Epoch: 004/050 | Batch 250/600 | Cost: 0.0292\n",
      "Epoch: 004/050 | Batch 300/600 | Cost: 0.0350\n",
      "Epoch: 004/050 | Batch 350/600 | Cost: 0.0312\n",
      "Epoch: 004/050 | Batch 400/600 | Cost: 0.0276\n",
      "Epoch: 004/050 | Batch 450/600 | Cost: 0.0312\n",
      "Epoch: 004/050 | Batch 500/600 | Cost: 0.0315\n",
      "Epoch: 004/050 | Batch 550/600 | Cost: 0.0291\n",
      "Epoch: 004/050 | Train MSE: 0.02692\n",
      "Epoch: 005/050 | Batch 000/600 | Cost: 0.0282\n",
      "Epoch: 005/050 | Batch 050/600 | Cost: 0.0264\n",
      "Epoch: 005/050 | Batch 100/600 | Cost: 0.0231\n",
      "Epoch: 005/050 | Batch 150/600 | Cost: 0.0242\n",
      "Epoch: 005/050 | Batch 200/600 | Cost: 0.0260\n",
      "Epoch: 005/050 | Batch 250/600 | Cost: 0.0215\n",
      "Epoch: 005/050 | Batch 300/600 | Cost: 0.0294\n",
      "Epoch: 005/050 | Batch 350/600 | Cost: 0.0220\n",
      "Epoch: 005/050 | Batch 400/600 | Cost: 0.0246\n",
      "Epoch: 005/050 | Batch 450/600 | Cost: 0.0229\n",
      "Epoch: 005/050 | Batch 500/600 | Cost: 0.0289\n",
      "Epoch: 005/050 | Batch 550/600 | Cost: 0.0240\n",
      "Epoch: 005/050 | Train MSE: 0.02365\n",
      "Epoch: 006/050 | Batch 000/600 | Cost: 0.0201\n",
      "Epoch: 006/050 | Batch 050/600 | Cost: 0.0223\n",
      "Epoch: 006/050 | Batch 100/600 | Cost: 0.0253\n",
      "Epoch: 006/050 | Batch 150/600 | Cost: 0.0258\n",
      "Epoch: 006/050 | Batch 200/600 | Cost: 0.0216\n",
      "Epoch: 006/050 | Batch 250/600 | Cost: 0.0282\n",
      "Epoch: 006/050 | Batch 300/600 | Cost: 0.0203\n",
      "Epoch: 006/050 | Batch 350/600 | Cost: 0.0218\n",
      "Epoch: 006/050 | Batch 400/600 | Cost: 0.0249\n",
      "Epoch: 006/050 | Batch 450/600 | Cost: 0.0211\n",
      "Epoch: 006/050 | Batch 500/600 | Cost: 0.0230\n",
      "Epoch: 006/050 | Batch 550/600 | Cost: 0.0174\n",
      "Epoch: 006/050 | Train MSE: 0.02156\n",
      "Epoch: 007/050 | Batch 000/600 | Cost: 0.0186\n",
      "Epoch: 007/050 | Batch 050/600 | Cost: 0.0223\n",
      "Epoch: 007/050 | Batch 100/600 | Cost: 0.0208\n",
      "Epoch: 007/050 | Batch 150/600 | Cost: 0.0231\n",
      "Epoch: 007/050 | Batch 200/600 | Cost: 0.0219\n",
      "Epoch: 007/050 | Batch 250/600 | Cost: 0.0206\n",
      "Epoch: 007/050 | Batch 300/600 | Cost: 0.0227\n",
      "Epoch: 007/050 | Batch 350/600 | Cost: 0.0249\n",
      "Epoch: 007/050 | Batch 400/600 | Cost: 0.0214\n",
      "Epoch: 007/050 | Batch 450/600 | Cost: 0.0203\n",
      "Epoch: 007/050 | Batch 500/600 | Cost: 0.0209\n",
      "Epoch: 007/050 | Batch 550/600 | Cost: 0.0160\n",
      "Epoch: 007/050 | Train MSE: 0.02006\n",
      "Epoch: 008/050 | Batch 000/600 | Cost: 0.0171\n",
      "Epoch: 008/050 | Batch 050/600 | Cost: 0.0232\n",
      "Epoch: 008/050 | Batch 100/600 | Cost: 0.0227\n",
      "Epoch: 008/050 | Batch 150/600 | Cost: 0.0156\n",
      "Epoch: 008/050 | Batch 200/600 | Cost: 0.0157\n",
      "Epoch: 008/050 | Batch 250/600 | Cost: 0.0189\n",
      "Epoch: 008/050 | Batch 300/600 | Cost: 0.0154\n",
      "Epoch: 008/050 | Batch 350/600 | Cost: 0.0213\n",
      "Epoch: 008/050 | Batch 400/600 | Cost: 0.0158\n",
      "Epoch: 008/050 | Batch 450/600 | Cost: 0.0201\n",
      "Epoch: 008/050 | Batch 500/600 | Cost: 0.0176\n",
      "Epoch: 008/050 | Batch 550/600 | Cost: 0.0254\n",
      "Epoch: 008/050 | Train MSE: 0.01892\n",
      "Epoch: 009/050 | Batch 000/600 | Cost: 0.0195\n",
      "Epoch: 009/050 | Batch 050/600 | Cost: 0.0214\n",
      "Epoch: 009/050 | Batch 100/600 | Cost: 0.0255\n",
      "Epoch: 009/050 | Batch 150/600 | Cost: 0.0153\n",
      "Epoch: 009/050 | Batch 200/600 | Cost: 0.0184\n",
      "Epoch: 009/050 | Batch 250/600 | Cost: 0.0247\n",
      "Epoch: 009/050 | Batch 300/600 | Cost: 0.0151\n",
      "Epoch: 009/050 | Batch 350/600 | Cost: 0.0165\n",
      "Epoch: 009/050 | Batch 400/600 | Cost: 0.0171\n",
      "Epoch: 009/050 | Batch 450/600 | Cost: 0.0136\n",
      "Epoch: 009/050 | Batch 500/600 | Cost: 0.0206\n",
      "Epoch: 009/050 | Batch 550/600 | Cost: 0.0142\n",
      "Epoch: 009/050 | Train MSE: 0.01803\n",
      "Epoch: 010/050 | Batch 000/600 | Cost: 0.0183\n",
      "Epoch: 010/050 | Batch 050/600 | Cost: 0.0222\n",
      "Epoch: 010/050 | Batch 100/600 | Cost: 0.0203\n",
      "Epoch: 010/050 | Batch 150/600 | Cost: 0.0224\n",
      "Epoch: 010/050 | Batch 200/600 | Cost: 0.0234\n",
      "Epoch: 010/050 | Batch 250/600 | Cost: 0.0229\n",
      "Epoch: 010/050 | Batch 300/600 | Cost: 0.0179\n",
      "Epoch: 010/050 | Batch 350/600 | Cost: 0.0181\n",
      "Epoch: 010/050 | Batch 400/600 | Cost: 0.0122\n",
      "Epoch: 010/050 | Batch 450/600 | Cost: 0.0176\n",
      "Epoch: 010/050 | Batch 500/600 | Cost: 0.0198\n",
      "Epoch: 010/050 | Batch 550/600 | Cost: 0.0142\n",
      "Epoch: 010/050 | Train MSE: 0.01727\n",
      "Epoch: 011/050 | Batch 000/600 | Cost: 0.0156\n",
      "Epoch: 011/050 | Batch 050/600 | Cost: 0.0178\n",
      "Epoch: 011/050 | Batch 100/600 | Cost: 0.0102\n",
      "Epoch: 011/050 | Batch 150/600 | Cost: 0.0188\n",
      "Epoch: 011/050 | Batch 200/600 | Cost: 0.0177\n",
      "Epoch: 011/050 | Batch 250/600 | Cost: 0.0196\n",
      "Epoch: 011/050 | Batch 300/600 | Cost: 0.0115\n",
      "Epoch: 011/050 | Batch 350/600 | Cost: 0.0109\n",
      "Epoch: 011/050 | Batch 400/600 | Cost: 0.0212\n",
      "Epoch: 011/050 | Batch 450/600 | Cost: 0.0162\n",
      "Epoch: 011/050 | Batch 500/600 | Cost: 0.0139\n",
      "Epoch: 011/050 | Batch 550/600 | Cost: 0.0144\n",
      "Epoch: 011/050 | Train MSE: 0.01665\n",
      "Epoch: 012/050 | Batch 000/600 | Cost: 0.0185\n",
      "Epoch: 012/050 | Batch 050/600 | Cost: 0.0137\n",
      "Epoch: 012/050 | Batch 100/600 | Cost: 0.0160\n",
      "Epoch: 012/050 | Batch 150/600 | Cost: 0.0142\n",
      "Epoch: 012/050 | Batch 200/600 | Cost: 0.0138\n",
      "Epoch: 012/050 | Batch 250/600 | Cost: 0.0169\n",
      "Epoch: 012/050 | Batch 300/600 | Cost: 0.0141\n",
      "Epoch: 012/050 | Batch 350/600 | Cost: 0.0137\n",
      "Epoch: 012/050 | Batch 400/600 | Cost: 0.0134\n",
      "Epoch: 012/050 | Batch 450/600 | Cost: 0.0141\n",
      "Epoch: 012/050 | Batch 500/600 | Cost: 0.0139\n",
      "Epoch: 012/050 | Batch 550/600 | Cost: 0.0175\n",
      "Epoch: 012/050 | Train MSE: 0.01609\n",
      "Epoch: 013/050 | Batch 000/600 | Cost: 0.0197\n",
      "Epoch: 013/050 | Batch 050/600 | Cost: 0.0134\n",
      "Epoch: 013/050 | Batch 100/600 | Cost: 0.0213\n",
      "Epoch: 013/050 | Batch 150/600 | Cost: 0.0172\n",
      "Epoch: 013/050 | Batch 200/600 | Cost: 0.0149\n",
      "Epoch: 013/050 | Batch 250/600 | Cost: 0.0155\n",
      "Epoch: 013/050 | Batch 300/600 | Cost: 0.0224\n",
      "Epoch: 013/050 | Batch 350/600 | Cost: 0.0177\n",
      "Epoch: 013/050 | Batch 400/600 | Cost: 0.0125\n",
      "Epoch: 013/050 | Batch 450/600 | Cost: 0.0191\n",
      "Epoch: 013/050 | Batch 500/600 | Cost: 0.0196\n",
      "Epoch: 013/050 | Batch 550/600 | Cost: 0.0167\n",
      "Epoch: 013/050 | Train MSE: 0.01561\n",
      "Epoch: 014/050 | Batch 000/600 | Cost: 0.0206\n",
      "Epoch: 014/050 | Batch 050/600 | Cost: 0.0139\n",
      "Epoch: 014/050 | Batch 100/600 | Cost: 0.0145\n",
      "Epoch: 014/050 | Batch 150/600 | Cost: 0.0210\n",
      "Epoch: 014/050 | Batch 200/600 | Cost: 0.0113\n",
      "Epoch: 014/050 | Batch 250/600 | Cost: 0.0160\n",
      "Epoch: 014/050 | Batch 300/600 | Cost: 0.0188\n",
      "Epoch: 014/050 | Batch 350/600 | Cost: 0.0247\n",
      "Epoch: 014/050 | Batch 400/600 | Cost: 0.0208\n",
      "Epoch: 014/050 | Batch 450/600 | Cost: 0.0170\n",
      "Epoch: 014/050 | Batch 500/600 | Cost: 0.0148\n",
      "Epoch: 014/050 | Batch 550/600 | Cost: 0.0197\n",
      "Epoch: 014/050 | Train MSE: 0.01518\n",
      "Epoch: 015/050 | Batch 000/600 | Cost: 0.0138\n",
      "Epoch: 015/050 | Batch 050/600 | Cost: 0.0183\n",
      "Epoch: 015/050 | Batch 100/600 | Cost: 0.0117\n",
      "Epoch: 015/050 | Batch 150/600 | Cost: 0.0123\n",
      "Epoch: 015/050 | Batch 200/600 | Cost: 0.0114\n",
      "Epoch: 015/050 | Batch 250/600 | Cost: 0.0116\n",
      "Epoch: 015/050 | Batch 300/600 | Cost: 0.0199\n",
      "Epoch: 015/050 | Batch 350/600 | Cost: 0.0165\n",
      "Epoch: 015/050 | Batch 400/600 | Cost: 0.0199\n",
      "Epoch: 015/050 | Batch 450/600 | Cost: 0.0143\n",
      "Epoch: 015/050 | Batch 500/600 | Cost: 0.0148\n",
      "Epoch: 015/050 | Batch 550/600 | Cost: 0.0130\n",
      "Epoch: 015/050 | Train MSE: 0.01481\n",
      "Epoch: 016/050 | Batch 000/600 | Cost: 0.0195\n",
      "Epoch: 016/050 | Batch 050/600 | Cost: 0.0150\n",
      "Epoch: 016/050 | Batch 100/600 | Cost: 0.0145\n",
      "Epoch: 016/050 | Batch 150/600 | Cost: 0.0139\n",
      "Epoch: 016/050 | Batch 200/600 | Cost: 0.0108\n",
      "Epoch: 016/050 | Batch 250/600 | Cost: 0.0110\n",
      "Epoch: 016/050 | Batch 300/600 | Cost: 0.0119\n",
      "Epoch: 016/050 | Batch 350/600 | Cost: 0.0175\n",
      "Epoch: 016/050 | Batch 400/600 | Cost: 0.0133\n",
      "Epoch: 016/050 | Batch 450/600 | Cost: 0.0144\n",
      "Epoch: 016/050 | Batch 500/600 | Cost: 0.0168\n",
      "Epoch: 016/050 | Batch 550/600 | Cost: 0.0131\n",
      "Epoch: 016/050 | Train MSE: 0.01447\n",
      "Epoch: 017/050 | Batch 000/600 | Cost: 0.0128\n",
      "Epoch: 017/050 | Batch 050/600 | Cost: 0.0160\n",
      "Epoch: 017/050 | Batch 100/600 | Cost: 0.0183\n",
      "Epoch: 017/050 | Batch 150/600 | Cost: 0.0136\n",
      "Epoch: 017/050 | Batch 200/600 | Cost: 0.0144\n",
      "Epoch: 017/050 | Batch 250/600 | Cost: 0.0109\n",
      "Epoch: 017/050 | Batch 300/600 | Cost: 0.0104\n",
      "Epoch: 017/050 | Batch 350/600 | Cost: 0.0146\n",
      "Epoch: 017/050 | Batch 400/600 | Cost: 0.0099\n",
      "Epoch: 017/050 | Batch 450/600 | Cost: 0.0096\n",
      "Epoch: 017/050 | Batch 500/600 | Cost: 0.0145\n",
      "Epoch: 017/050 | Batch 550/600 | Cost: 0.0160\n",
      "Epoch: 017/050 | Train MSE: 0.01415\n",
      "Epoch: 018/050 | Batch 000/600 | Cost: 0.0140\n",
      "Epoch: 018/050 | Batch 050/600 | Cost: 0.0145\n",
      "Epoch: 018/050 | Batch 100/600 | Cost: 0.0167\n",
      "Epoch: 018/050 | Batch 150/600 | Cost: 0.0136\n",
      "Epoch: 018/050 | Batch 200/600 | Cost: 0.0102\n",
      "Epoch: 018/050 | Batch 250/600 | Cost: 0.0164\n",
      "Epoch: 018/050 | Batch 300/600 | Cost: 0.0094\n",
      "Epoch: 018/050 | Batch 350/600 | Cost: 0.0169\n",
      "Epoch: 018/050 | Batch 400/600 | Cost: 0.0108\n",
      "Epoch: 018/050 | Batch 450/600 | Cost: 0.0155\n",
      "Epoch: 018/050 | Batch 500/600 | Cost: 0.0106\n",
      "Epoch: 018/050 | Batch 550/600 | Cost: 0.0143\n",
      "Epoch: 018/050 | Train MSE: 0.01386\n",
      "Epoch: 019/050 | Batch 000/600 | Cost: 0.0226\n",
      "Epoch: 019/050 | Batch 050/600 | Cost: 0.0175\n",
      "Epoch: 019/050 | Batch 100/600 | Cost: 0.0165\n",
      "Epoch: 019/050 | Batch 150/600 | Cost: 0.0118\n",
      "Epoch: 019/050 | Batch 200/600 | Cost: 0.0174\n",
      "Epoch: 019/050 | Batch 250/600 | Cost: 0.0132\n",
      "Epoch: 019/050 | Batch 300/600 | Cost: 0.0136\n",
      "Epoch: 019/050 | Batch 350/600 | Cost: 0.0090\n",
      "Epoch: 019/050 | Batch 400/600 | Cost: 0.0064\n",
      "Epoch: 019/050 | Batch 450/600 | Cost: 0.0168\n",
      "Epoch: 019/050 | Batch 500/600 | Cost: 0.0135\n",
      "Epoch: 019/050 | Batch 550/600 | Cost: 0.0166\n",
      "Epoch: 019/050 | Train MSE: 0.01360\n",
      "Epoch: 020/050 | Batch 000/600 | Cost: 0.0184\n",
      "Epoch: 020/050 | Batch 050/600 | Cost: 0.0124\n",
      "Epoch: 020/050 | Batch 100/600 | Cost: 0.0142\n",
      "Epoch: 020/050 | Batch 150/600 | Cost: 0.0167\n",
      "Epoch: 020/050 | Batch 200/600 | Cost: 0.0140\n",
      "Epoch: 020/050 | Batch 250/600 | Cost: 0.0112\n",
      "Epoch: 020/050 | Batch 300/600 | Cost: 0.0140\n",
      "Epoch: 020/050 | Batch 350/600 | Cost: 0.0115\n",
      "Epoch: 020/050 | Batch 400/600 | Cost: 0.0106\n",
      "Epoch: 020/050 | Batch 450/600 | Cost: 0.0156\n",
      "Epoch: 020/050 | Batch 500/600 | Cost: 0.0150\n",
      "Epoch: 020/050 | Batch 550/600 | Cost: 0.0113\n",
      "Epoch: 020/050 | Train MSE: 0.01335\n",
      "Epoch: 021/050 | Batch 000/600 | Cost: 0.0127\n",
      "Epoch: 021/050 | Batch 050/600 | Cost: 0.0100\n",
      "Epoch: 021/050 | Batch 100/600 | Cost: 0.0183\n",
      "Epoch: 021/050 | Batch 150/600 | Cost: 0.0138\n",
      "Epoch: 021/050 | Batch 200/600 | Cost: 0.0120\n",
      "Epoch: 021/050 | Batch 250/600 | Cost: 0.0115\n",
      "Epoch: 021/050 | Batch 300/600 | Cost: 0.0125\n",
      "Epoch: 021/050 | Batch 350/600 | Cost: 0.0085\n",
      "Epoch: 021/050 | Batch 400/600 | Cost: 0.0121\n",
      "Epoch: 021/050 | Batch 450/600 | Cost: 0.0140\n",
      "Epoch: 021/050 | Batch 500/600 | Cost: 0.0098\n",
      "Epoch: 021/050 | Batch 550/600 | Cost: 0.0145\n",
      "Epoch: 021/050 | Train MSE: 0.01312\n",
      "Epoch: 022/050 | Batch 000/600 | Cost: 0.0141\n",
      "Epoch: 022/050 | Batch 050/600 | Cost: 0.0147\n",
      "Epoch: 022/050 | Batch 100/600 | Cost: 0.0172\n",
      "Epoch: 022/050 | Batch 150/600 | Cost: 0.0161\n",
      "Epoch: 022/050 | Batch 200/600 | Cost: 0.0108\n",
      "Epoch: 022/050 | Batch 250/600 | Cost: 0.0108\n",
      "Epoch: 022/050 | Batch 300/600 | Cost: 0.0149\n",
      "Epoch: 022/050 | Batch 350/600 | Cost: 0.0133\n",
      "Epoch: 022/050 | Batch 400/600 | Cost: 0.0077\n",
      "Epoch: 022/050 | Batch 450/600 | Cost: 0.0101\n",
      "Epoch: 022/050 | Batch 500/600 | Cost: 0.0177\n",
      "Epoch: 022/050 | Batch 550/600 | Cost: 0.0120\n",
      "Epoch: 022/050 | Train MSE: 0.01291\n",
      "Epoch: 023/050 | Batch 000/600 | Cost: 0.0165\n",
      "Epoch: 023/050 | Batch 050/600 | Cost: 0.0132\n",
      "Epoch: 023/050 | Batch 100/600 | Cost: 0.0169\n",
      "Epoch: 023/050 | Batch 150/600 | Cost: 0.0135\n",
      "Epoch: 023/050 | Batch 200/600 | Cost: 0.0133\n",
      "Epoch: 023/050 | Batch 250/600 | Cost: 0.0137\n",
      "Epoch: 023/050 | Batch 300/600 | Cost: 0.0149\n",
      "Epoch: 023/050 | Batch 350/600 | Cost: 0.0185\n",
      "Epoch: 023/050 | Batch 400/600 | Cost: 0.0091\n",
      "Epoch: 023/050 | Batch 450/600 | Cost: 0.0141\n",
      "Epoch: 023/050 | Batch 500/600 | Cost: 0.0170\n",
      "Epoch: 023/050 | Batch 550/600 | Cost: 0.0096\n",
      "Epoch: 023/050 | Train MSE: 0.01270\n",
      "Epoch: 024/050 | Batch 000/600 | Cost: 0.0122\n",
      "Epoch: 024/050 | Batch 050/600 | Cost: 0.0095\n",
      "Epoch: 024/050 | Batch 100/600 | Cost: 0.0099\n",
      "Epoch: 024/050 | Batch 150/600 | Cost: 0.0063\n",
      "Epoch: 024/050 | Batch 200/600 | Cost: 0.0133\n",
      "Epoch: 024/050 | Batch 250/600 | Cost: 0.0108\n",
      "Epoch: 024/050 | Batch 300/600 | Cost: 0.0149\n",
      "Epoch: 024/050 | Batch 350/600 | Cost: 0.0143\n",
      "Epoch: 024/050 | Batch 400/600 | Cost: 0.0124\n",
      "Epoch: 024/050 | Batch 450/600 | Cost: 0.0116\n",
      "Epoch: 024/050 | Batch 500/600 | Cost: 0.0083\n",
      "Epoch: 024/050 | Batch 550/600 | Cost: 0.0079\n",
      "Epoch: 024/050 | Train MSE: 0.01251\n",
      "Epoch: 025/050 | Batch 000/600 | Cost: 0.0147\n",
      "Epoch: 025/050 | Batch 050/600 | Cost: 0.0104\n",
      "Epoch: 025/050 | Batch 100/600 | Cost: 0.0120\n",
      "Epoch: 025/050 | Batch 150/600 | Cost: 0.0127\n",
      "Epoch: 025/050 | Batch 200/600 | Cost: 0.0094\n",
      "Epoch: 025/050 | Batch 250/600 | Cost: 0.0085\n",
      "Epoch: 025/050 | Batch 300/600 | Cost: 0.0138\n",
      "Epoch: 025/050 | Batch 350/600 | Cost: 0.0086\n",
      "Epoch: 025/050 | Batch 400/600 | Cost: 0.0130\n",
      "Epoch: 025/050 | Batch 450/600 | Cost: 0.0136\n",
      "Epoch: 025/050 | Batch 500/600 | Cost: 0.0135\n",
      "Epoch: 025/050 | Batch 550/600 | Cost: 0.0155\n",
      "Epoch: 025/050 | Train MSE: 0.01232\n",
      "Epoch: 026/050 | Batch 000/600 | Cost: 0.0138\n",
      "Epoch: 026/050 | Batch 050/600 | Cost: 0.0136\n",
      "Epoch: 026/050 | Batch 100/600 | Cost: 0.0076\n",
      "Epoch: 026/050 | Batch 150/600 | Cost: 0.0179\n",
      "Epoch: 026/050 | Batch 200/600 | Cost: 0.0119\n",
      "Epoch: 026/050 | Batch 250/600 | Cost: 0.0142\n",
      "Epoch: 026/050 | Batch 300/600 | Cost: 0.0138\n",
      "Epoch: 026/050 | Batch 350/600 | Cost: 0.0107\n",
      "Epoch: 026/050 | Batch 400/600 | Cost: 0.0103\n",
      "Epoch: 026/050 | Batch 450/600 | Cost: 0.0091\n",
      "Epoch: 026/050 | Batch 500/600 | Cost: 0.0116\n",
      "Epoch: 026/050 | Batch 550/600 | Cost: 0.0091\n",
      "Epoch: 026/050 | Train MSE: 0.01215\n",
      "Epoch: 027/050 | Batch 000/600 | Cost: 0.0085\n",
      "Epoch: 027/050 | Batch 050/600 | Cost: 0.0065\n",
      "Epoch: 027/050 | Batch 100/600 | Cost: 0.0102\n",
      "Epoch: 027/050 | Batch 150/600 | Cost: 0.0152\n",
      "Epoch: 027/050 | Batch 200/600 | Cost: 0.0162\n",
      "Epoch: 027/050 | Batch 250/600 | Cost: 0.0079\n",
      "Epoch: 027/050 | Batch 300/600 | Cost: 0.0118\n",
      "Epoch: 027/050 | Batch 350/600 | Cost: 0.0111\n",
      "Epoch: 027/050 | Batch 400/600 | Cost: 0.0081\n",
      "Epoch: 027/050 | Batch 450/600 | Cost: 0.0100\n",
      "Epoch: 027/050 | Batch 500/600 | Cost: 0.0103\n",
      "Epoch: 027/050 | Batch 550/600 | Cost: 0.0117\n",
      "Epoch: 027/050 | Train MSE: 0.01199\n",
      "Epoch: 028/050 | Batch 000/600 | Cost: 0.0077\n",
      "Epoch: 028/050 | Batch 050/600 | Cost: 0.0164\n",
      "Epoch: 028/050 | Batch 100/600 | Cost: 0.0095\n",
      "Epoch: 028/050 | Batch 150/600 | Cost: 0.0112\n",
      "Epoch: 028/050 | Batch 200/600 | Cost: 0.0109\n",
      "Epoch: 028/050 | Batch 250/600 | Cost: 0.0148\n",
      "Epoch: 028/050 | Batch 300/600 | Cost: 0.0126\n",
      "Epoch: 028/050 | Batch 350/600 | Cost: 0.0082\n",
      "Epoch: 028/050 | Batch 400/600 | Cost: 0.0115\n",
      "Epoch: 028/050 | Batch 450/600 | Cost: 0.0194\n",
      "Epoch: 028/050 | Batch 500/600 | Cost: 0.0111\n",
      "Epoch: 028/050 | Batch 550/600 | Cost: 0.0145\n",
      "Epoch: 028/050 | Train MSE: 0.01181\n",
      "Epoch: 029/050 | Batch 000/600 | Cost: 0.0112\n",
      "Epoch: 029/050 | Batch 050/600 | Cost: 0.0137\n",
      "Epoch: 029/050 | Batch 100/600 | Cost: 0.0192\n",
      "Epoch: 029/050 | Batch 150/600 | Cost: 0.0105\n",
      "Epoch: 029/050 | Batch 200/600 | Cost: 0.0107\n",
      "Epoch: 029/050 | Batch 250/600 | Cost: 0.0081\n",
      "Epoch: 029/050 | Batch 300/600 | Cost: 0.0079\n",
      "Epoch: 029/050 | Batch 350/600 | Cost: 0.0126\n",
      "Epoch: 029/050 | Batch 400/600 | Cost: 0.0135\n",
      "Epoch: 029/050 | Batch 450/600 | Cost: 0.0062\n",
      "Epoch: 029/050 | Batch 500/600 | Cost: 0.0121\n",
      "Epoch: 029/050 | Batch 550/600 | Cost: 0.0091\n",
      "Epoch: 029/050 | Train MSE: 0.01167\n",
      "Epoch: 030/050 | Batch 000/600 | Cost: 0.0068\n",
      "Epoch: 030/050 | Batch 050/600 | Cost: 0.0115\n",
      "Epoch: 030/050 | Batch 100/600 | Cost: 0.0145\n",
      "Epoch: 030/050 | Batch 150/600 | Cost: 0.0128\n",
      "Epoch: 030/050 | Batch 200/600 | Cost: 0.0129\n",
      "Epoch: 030/050 | Batch 250/600 | Cost: 0.0128\n",
      "Epoch: 030/050 | Batch 300/600 | Cost: 0.0085\n",
      "Epoch: 030/050 | Batch 350/600 | Cost: 0.0149\n",
      "Epoch: 030/050 | Batch 400/600 | Cost: 0.0080\n",
      "Epoch: 030/050 | Batch 450/600 | Cost: 0.0168\n",
      "Epoch: 030/050 | Batch 500/600 | Cost: 0.0106\n",
      "Epoch: 030/050 | Batch 550/600 | Cost: 0.0125\n",
      "Epoch: 030/050 | Train MSE: 0.01152\n",
      "Epoch: 031/050 | Batch 000/600 | Cost: 0.0137\n",
      "Epoch: 031/050 | Batch 050/600 | Cost: 0.0080\n",
      "Epoch: 031/050 | Batch 100/600 | Cost: 0.0122\n",
      "Epoch: 031/050 | Batch 150/600 | Cost: 0.0121\n",
      "Epoch: 031/050 | Batch 200/600 | Cost: 0.0125\n",
      "Epoch: 031/050 | Batch 250/600 | Cost: 0.0120\n",
      "Epoch: 031/050 | Batch 300/600 | Cost: 0.0123\n",
      "Epoch: 031/050 | Batch 350/600 | Cost: 0.0166\n",
      "Epoch: 031/050 | Batch 400/600 | Cost: 0.0099\n",
      "Epoch: 031/050 | Batch 450/600 | Cost: 0.0099\n",
      "Epoch: 031/050 | Batch 500/600 | Cost: 0.0103\n",
      "Epoch: 031/050 | Batch 550/600 | Cost: 0.0099\n",
      "Epoch: 031/050 | Train MSE: 0.01138\n",
      "Epoch: 032/050 | Batch 000/600 | Cost: 0.0125\n",
      "Epoch: 032/050 | Batch 050/600 | Cost: 0.0114\n",
      "Epoch: 032/050 | Batch 100/600 | Cost: 0.0118\n",
      "Epoch: 032/050 | Batch 150/600 | Cost: 0.0110\n",
      "Epoch: 032/050 | Batch 200/600 | Cost: 0.0137\n",
      "Epoch: 032/050 | Batch 250/600 | Cost: 0.0156\n",
      "Epoch: 032/050 | Batch 300/600 | Cost: 0.0084\n",
      "Epoch: 032/050 | Batch 350/600 | Cost: 0.0187\n",
      "Epoch: 032/050 | Batch 400/600 | Cost: 0.0101\n",
      "Epoch: 032/050 | Batch 450/600 | Cost: 0.0071\n",
      "Epoch: 032/050 | Batch 500/600 | Cost: 0.0104\n",
      "Epoch: 032/050 | Batch 550/600 | Cost: 0.0135\n",
      "Epoch: 032/050 | Train MSE: 0.01126\n",
      "Epoch: 033/050 | Batch 000/600 | Cost: 0.0159\n",
      "Epoch: 033/050 | Batch 050/600 | Cost: 0.0126\n",
      "Epoch: 033/050 | Batch 100/600 | Cost: 0.0077\n",
      "Epoch: 033/050 | Batch 150/600 | Cost: 0.0093\n",
      "Epoch: 033/050 | Batch 200/600 | Cost: 0.0092\n",
      "Epoch: 033/050 | Batch 250/600 | Cost: 0.0128\n",
      "Epoch: 033/050 | Batch 300/600 | Cost: 0.0095\n",
      "Epoch: 033/050 | Batch 350/600 | Cost: 0.0108\n",
      "Epoch: 033/050 | Batch 400/600 | Cost: 0.0116\n",
      "Epoch: 033/050 | Batch 450/600 | Cost: 0.0082\n",
      "Epoch: 033/050 | Batch 500/600 | Cost: 0.0151\n",
      "Epoch: 033/050 | Batch 550/600 | Cost: 0.0097\n",
      "Epoch: 033/050 | Train MSE: 0.01112\n",
      "Epoch: 034/050 | Batch 000/600 | Cost: 0.0119\n",
      "Epoch: 034/050 | Batch 050/600 | Cost: 0.0079\n",
      "Epoch: 034/050 | Batch 100/600 | Cost: 0.0118\n",
      "Epoch: 034/050 | Batch 150/600 | Cost: 0.0122\n",
      "Epoch: 034/050 | Batch 200/600 | Cost: 0.0078\n",
      "Epoch: 034/050 | Batch 250/600 | Cost: 0.0142\n",
      "Epoch: 034/050 | Batch 300/600 | Cost: 0.0066\n",
      "Epoch: 034/050 | Batch 350/600 | Cost: 0.0112\n",
      "Epoch: 034/050 | Batch 400/600 | Cost: 0.0067\n",
      "Epoch: 034/050 | Batch 450/600 | Cost: 0.0105\n",
      "Epoch: 034/050 | Batch 500/600 | Cost: 0.0119\n",
      "Epoch: 034/050 | Batch 550/600 | Cost: 0.0145\n",
      "Epoch: 034/050 | Train MSE: 0.01099\n",
      "Epoch: 035/050 | Batch 000/600 | Cost: 0.0100\n",
      "Epoch: 035/050 | Batch 050/600 | Cost: 0.0072\n",
      "Epoch: 035/050 | Batch 100/600 | Cost: 0.0071\n",
      "Epoch: 035/050 | Batch 150/600 | Cost: 0.0111\n",
      "Epoch: 035/050 | Batch 200/600 | Cost: 0.0096\n",
      "Epoch: 035/050 | Batch 250/600 | Cost: 0.0089\n",
      "Epoch: 035/050 | Batch 300/600 | Cost: 0.0098\n",
      "Epoch: 035/050 | Batch 350/600 | Cost: 0.0116\n",
      "Epoch: 035/050 | Batch 400/600 | Cost: 0.0128\n",
      "Epoch: 035/050 | Batch 450/600 | Cost: 0.0091\n",
      "Epoch: 035/050 | Batch 500/600 | Cost: 0.0093\n",
      "Epoch: 035/050 | Batch 550/600 | Cost: 0.0103\n",
      "Epoch: 035/050 | Train MSE: 0.01088\n",
      "Epoch: 036/050 | Batch 000/600 | Cost: 0.0065\n",
      "Epoch: 036/050 | Batch 050/600 | Cost: 0.0164\n",
      "Epoch: 036/050 | Batch 100/600 | Cost: 0.0118\n",
      "Epoch: 036/050 | Batch 150/600 | Cost: 0.0075\n",
      "Epoch: 036/050 | Batch 200/600 | Cost: 0.0193\n",
      "Epoch: 036/050 | Batch 250/600 | Cost: 0.0208\n",
      "Epoch: 036/050 | Batch 300/600 | Cost: 0.0096\n",
      "Epoch: 036/050 | Batch 350/600 | Cost: 0.0084\n",
      "Epoch: 036/050 | Batch 400/600 | Cost: 0.0096\n",
      "Epoch: 036/050 | Batch 450/600 | Cost: 0.0109\n",
      "Epoch: 036/050 | Batch 500/600 | Cost: 0.0104\n",
      "Epoch: 036/050 | Batch 550/600 | Cost: 0.0063\n",
      "Epoch: 036/050 | Train MSE: 0.01076\n",
      "Epoch: 037/050 | Batch 000/600 | Cost: 0.0092\n",
      "Epoch: 037/050 | Batch 050/600 | Cost: 0.0120\n",
      "Epoch: 037/050 | Batch 100/600 | Cost: 0.0107\n",
      "Epoch: 037/050 | Batch 150/600 | Cost: 0.0139\n",
      "Epoch: 037/050 | Batch 200/600 | Cost: 0.0127\n",
      "Epoch: 037/050 | Batch 250/600 | Cost: 0.0082\n",
      "Epoch: 037/050 | Batch 300/600 | Cost: 0.0073\n",
      "Epoch: 037/050 | Batch 350/600 | Cost: 0.0072\n",
      "Epoch: 037/050 | Batch 400/600 | Cost: 0.0083\n",
      "Epoch: 037/050 | Batch 450/600 | Cost: 0.0087\n",
      "Epoch: 037/050 | Batch 500/600 | Cost: 0.0187\n",
      "Epoch: 037/050 | Batch 550/600 | Cost: 0.0128\n",
      "Epoch: 037/050 | Train MSE: 0.01064\n",
      "Epoch: 038/050 | Batch 000/600 | Cost: 0.0145\n",
      "Epoch: 038/050 | Batch 050/600 | Cost: 0.0082\n",
      "Epoch: 038/050 | Batch 100/600 | Cost: 0.0116\n",
      "Epoch: 038/050 | Batch 150/600 | Cost: 0.0114\n",
      "Epoch: 038/050 | Batch 200/600 | Cost: 0.0089\n",
      "Epoch: 038/050 | Batch 250/600 | Cost: 0.0110\n",
      "Epoch: 038/050 | Batch 300/600 | Cost: 0.0130\n",
      "Epoch: 038/050 | Batch 350/600 | Cost: 0.0155\n",
      "Epoch: 038/050 | Batch 400/600 | Cost: 0.0107\n",
      "Epoch: 038/050 | Batch 450/600 | Cost: 0.0076\n",
      "Epoch: 038/050 | Batch 500/600 | Cost: 0.0138\n",
      "Epoch: 038/050 | Batch 550/600 | Cost: 0.0123\n",
      "Epoch: 038/050 | Train MSE: 0.01054\n",
      "Epoch: 039/050 | Batch 000/600 | Cost: 0.0106\n",
      "Epoch: 039/050 | Batch 050/600 | Cost: 0.0153\n",
      "Epoch: 039/050 | Batch 100/600 | Cost: 0.0108\n",
      "Epoch: 039/050 | Batch 150/600 | Cost: 0.0097\n",
      "Epoch: 039/050 | Batch 200/600 | Cost: 0.0116\n",
      "Epoch: 039/050 | Batch 250/600 | Cost: 0.0123\n",
      "Epoch: 039/050 | Batch 300/600 | Cost: 0.0082\n",
      "Epoch: 039/050 | Batch 350/600 | Cost: 0.0114\n",
      "Epoch: 039/050 | Batch 400/600 | Cost: 0.0083\n",
      "Epoch: 039/050 | Batch 450/600 | Cost: 0.0162\n",
      "Epoch: 039/050 | Batch 500/600 | Cost: 0.0108\n",
      "Epoch: 039/050 | Batch 550/600 | Cost: 0.0110\n",
      "Epoch: 039/050 | Train MSE: 0.01043\n",
      "Epoch: 040/050 | Batch 000/600 | Cost: 0.0121\n",
      "Epoch: 040/050 | Batch 050/600 | Cost: 0.0137\n",
      "Epoch: 040/050 | Batch 100/600 | Cost: 0.0094\n",
      "Epoch: 040/050 | Batch 150/600 | Cost: 0.0080\n",
      "Epoch: 040/050 | Batch 200/600 | Cost: 0.0107\n",
      "Epoch: 040/050 | Batch 250/600 | Cost: 0.0092\n",
      "Epoch: 040/050 | Batch 300/600 | Cost: 0.0088\n",
      "Epoch: 040/050 | Batch 350/600 | Cost: 0.0097\n",
      "Epoch: 040/050 | Batch 400/600 | Cost: 0.0084\n",
      "Epoch: 040/050 | Batch 450/600 | Cost: 0.0134\n",
      "Epoch: 040/050 | Batch 500/600 | Cost: 0.0144\n",
      "Epoch: 040/050 | Batch 550/600 | Cost: 0.0094\n",
      "Epoch: 040/050 | Train MSE: 0.01033\n",
      "Epoch: 041/050 | Batch 000/600 | Cost: 0.0112\n",
      "Epoch: 041/050 | Batch 050/600 | Cost: 0.0063\n",
      "Epoch: 041/050 | Batch 100/600 | Cost: 0.0117\n",
      "Epoch: 041/050 | Batch 150/600 | Cost: 0.0126\n",
      "Epoch: 041/050 | Batch 200/600 | Cost: 0.0181\n",
      "Epoch: 041/050 | Batch 250/600 | Cost: 0.0158\n",
      "Epoch: 041/050 | Batch 300/600 | Cost: 0.0140\n",
      "Epoch: 041/050 | Batch 350/600 | Cost: 0.0109\n",
      "Epoch: 041/050 | Batch 400/600 | Cost: 0.0105\n",
      "Epoch: 041/050 | Batch 450/600 | Cost: 0.0130\n",
      "Epoch: 041/050 | Batch 500/600 | Cost: 0.0081\n",
      "Epoch: 041/050 | Batch 550/600 | Cost: 0.0126\n",
      "Epoch: 041/050 | Train MSE: 0.01023\n",
      "Epoch: 042/050 | Batch 000/600 | Cost: 0.0100\n",
      "Epoch: 042/050 | Batch 050/600 | Cost: 0.0114\n",
      "Epoch: 042/050 | Batch 100/600 | Cost: 0.0109\n",
      "Epoch: 042/050 | Batch 150/600 | Cost: 0.0066\n",
      "Epoch: 042/050 | Batch 200/600 | Cost: 0.0080\n",
      "Epoch: 042/050 | Batch 250/600 | Cost: 0.0101\n",
      "Epoch: 042/050 | Batch 300/600 | Cost: 0.0122\n",
      "Epoch: 042/050 | Batch 350/600 | Cost: 0.0108\n",
      "Epoch: 042/050 | Batch 400/600 | Cost: 0.0088\n",
      "Epoch: 042/050 | Batch 450/600 | Cost: 0.0132\n",
      "Epoch: 042/050 | Batch 500/600 | Cost: 0.0103\n",
      "Epoch: 042/050 | Batch 550/600 | Cost: 0.0083\n",
      "Epoch: 042/050 | Train MSE: 0.01013\n",
      "Epoch: 043/050 | Batch 000/600 | Cost: 0.0097\n",
      "Epoch: 043/050 | Batch 050/600 | Cost: 0.0103\n",
      "Epoch: 043/050 | Batch 100/600 | Cost: 0.0144\n",
      "Epoch: 043/050 | Batch 150/600 | Cost: 0.0095\n",
      "Epoch: 043/050 | Batch 200/600 | Cost: 0.0108\n",
      "Epoch: 043/050 | Batch 250/600 | Cost: 0.0124\n",
      "Epoch: 043/050 | Batch 300/600 | Cost: 0.0125\n",
      "Epoch: 043/050 | Batch 350/600 | Cost: 0.0117\n",
      "Epoch: 043/050 | Batch 400/600 | Cost: 0.0085\n",
      "Epoch: 043/050 | Batch 450/600 | Cost: 0.0097\n",
      "Epoch: 043/050 | Batch 500/600 | Cost: 0.0163\n",
      "Epoch: 043/050 | Batch 550/600 | Cost: 0.0099\n",
      "Epoch: 043/050 | Train MSE: 0.01005\n",
      "Epoch: 044/050 | Batch 000/600 | Cost: 0.0090\n",
      "Epoch: 044/050 | Batch 050/600 | Cost: 0.0079\n",
      "Epoch: 044/050 | Batch 100/600 | Cost: 0.0089\n",
      "Epoch: 044/050 | Batch 150/600 | Cost: 0.0110\n",
      "Epoch: 044/050 | Batch 200/600 | Cost: 0.0072\n",
      "Epoch: 044/050 | Batch 250/600 | Cost: 0.0089\n",
      "Epoch: 044/050 | Batch 300/600 | Cost: 0.0138\n",
      "Epoch: 044/050 | Batch 350/600 | Cost: 0.0069\n",
      "Epoch: 044/050 | Batch 400/600 | Cost: 0.0086\n",
      "Epoch: 044/050 | Batch 450/600 | Cost: 0.0100\n",
      "Epoch: 044/050 | Batch 500/600 | Cost: 0.0076\n",
      "Epoch: 044/050 | Batch 550/600 | Cost: 0.0076\n",
      "Epoch: 044/050 | Train MSE: 0.00995\n",
      "Epoch: 045/050 | Batch 000/600 | Cost: 0.0098\n",
      "Epoch: 045/050 | Batch 050/600 | Cost: 0.0064\n",
      "Epoch: 045/050 | Batch 100/600 | Cost: 0.0097\n",
      "Epoch: 045/050 | Batch 150/600 | Cost: 0.0077\n",
      "Epoch: 045/050 | Batch 200/600 | Cost: 0.0136\n",
      "Epoch: 045/050 | Batch 250/600 | Cost: 0.0181\n",
      "Epoch: 045/050 | Batch 300/600 | Cost: 0.0085\n",
      "Epoch: 045/050 | Batch 350/600 | Cost: 0.0102\n",
      "Epoch: 045/050 | Batch 400/600 | Cost: 0.0058\n",
      "Epoch: 045/050 | Batch 450/600 | Cost: 0.0099\n",
      "Epoch: 045/050 | Batch 500/600 | Cost: 0.0061\n",
      "Epoch: 045/050 | Batch 550/600 | Cost: 0.0077\n",
      "Epoch: 045/050 | Train MSE: 0.00986\n",
      "Epoch: 046/050 | Batch 000/600 | Cost: 0.0074\n",
      "Epoch: 046/050 | Batch 050/600 | Cost: 0.0109\n",
      "Epoch: 046/050 | Batch 100/600 | Cost: 0.0090\n",
      "Epoch: 046/050 | Batch 150/600 | Cost: 0.0079\n",
      "Epoch: 046/050 | Batch 200/600 | Cost: 0.0085\n",
      "Epoch: 046/050 | Batch 250/600 | Cost: 0.0104\n",
      "Epoch: 046/050 | Batch 300/600 | Cost: 0.0121\n",
      "Epoch: 046/050 | Batch 350/600 | Cost: 0.0101\n",
      "Epoch: 046/050 | Batch 400/600 | Cost: 0.0091\n",
      "Epoch: 046/050 | Batch 450/600 | Cost: 0.0114\n",
      "Epoch: 046/050 | Batch 500/600 | Cost: 0.0082\n",
      "Epoch: 046/050 | Batch 550/600 | Cost: 0.0104\n",
      "Epoch: 046/050 | Train MSE: 0.00978\n",
      "Epoch: 047/050 | Batch 000/600 | Cost: 0.0109\n",
      "Epoch: 047/050 | Batch 050/600 | Cost: 0.0111\n",
      "Epoch: 047/050 | Batch 100/600 | Cost: 0.0075\n",
      "Epoch: 047/050 | Batch 150/600 | Cost: 0.0144\n",
      "Epoch: 047/050 | Batch 200/600 | Cost: 0.0092\n",
      "Epoch: 047/050 | Batch 250/600 | Cost: 0.0080\n",
      "Epoch: 047/050 | Batch 300/600 | Cost: 0.0118\n",
      "Epoch: 047/050 | Batch 350/600 | Cost: 0.0110\n",
      "Epoch: 047/050 | Batch 400/600 | Cost: 0.0038\n",
      "Epoch: 047/050 | Batch 450/600 | Cost: 0.0159\n",
      "Epoch: 047/050 | Batch 500/600 | Cost: 0.0084\n",
      "Epoch: 047/050 | Batch 550/600 | Cost: 0.0110\n",
      "Epoch: 047/050 | Train MSE: 0.00969\n",
      "Epoch: 048/050 | Batch 000/600 | Cost: 0.0071\n",
      "Epoch: 048/050 | Batch 050/600 | Cost: 0.0095\n",
      "Epoch: 048/050 | Batch 100/600 | Cost: 0.0093\n",
      "Epoch: 048/050 | Batch 150/600 | Cost: 0.0144\n",
      "Epoch: 048/050 | Batch 200/600 | Cost: 0.0123\n",
      "Epoch: 048/050 | Batch 250/600 | Cost: 0.0070\n",
      "Epoch: 048/050 | Batch 300/600 | Cost: 0.0107\n",
      "Epoch: 048/050 | Batch 350/600 | Cost: 0.0123\n",
      "Epoch: 048/050 | Batch 400/600 | Cost: 0.0064\n",
      "Epoch: 048/050 | Batch 450/600 | Cost: 0.0129\n",
      "Epoch: 048/050 | Batch 500/600 | Cost: 0.0065\n",
      "Epoch: 048/050 | Batch 550/600 | Cost: 0.0121\n",
      "Epoch: 048/050 | Train MSE: 0.00961\n",
      "Epoch: 049/050 | Batch 000/600 | Cost: 0.0031\n",
      "Epoch: 049/050 | Batch 050/600 | Cost: 0.0115\n",
      "Epoch: 049/050 | Batch 100/600 | Cost: 0.0046\n",
      "Epoch: 049/050 | Batch 150/600 | Cost: 0.0104\n",
      "Epoch: 049/050 | Batch 200/600 | Cost: 0.0070\n",
      "Epoch: 049/050 | Batch 250/600 | Cost: 0.0056\n",
      "Epoch: 049/050 | Batch 300/600 | Cost: 0.0114\n",
      "Epoch: 049/050 | Batch 350/600 | Cost: 0.0099\n",
      "Epoch: 049/050 | Batch 400/600 | Cost: 0.0110\n",
      "Epoch: 049/050 | Batch 450/600 | Cost: 0.0077\n",
      "Epoch: 049/050 | Batch 500/600 | Cost: 0.0071\n",
      "Epoch: 049/050 | Batch 550/600 | Cost: 0.0120\n",
      "Epoch: 049/050 | Train MSE: 0.00953\n",
      "Epoch: 050/050 | Batch 000/600 | Cost: 0.0113\n",
      "Epoch: 050/050 | Batch 050/600 | Cost: 0.0132\n",
      "Epoch: 050/050 | Batch 100/600 | Cost: 0.0060\n",
      "Epoch: 050/050 | Batch 150/600 | Cost: 0.0071\n",
      "Epoch: 050/050 | Batch 200/600 | Cost: 0.0069\n",
      "Epoch: 050/050 | Batch 250/600 | Cost: 0.0151\n",
      "Epoch: 050/050 | Batch 300/600 | Cost: 0.0106\n",
      "Epoch: 050/050 | Batch 350/600 | Cost: 0.0122\n",
      "Epoch: 050/050 | Batch 400/600 | Cost: 0.0081\n",
      "Epoch: 050/050 | Batch 450/600 | Cost: 0.0095\n",
      "Epoch: 050/050 | Batch 500/600 | Cost: 0.0122\n",
      "Epoch: 050/050 | Batch 550/600 | Cost: 0.0075\n",
      "Epoch: 050/050 | Train MSE: 0.00945\n"
     ]
    }
   ],
   "source": [
    "####################################################\n",
    "##### Training \n",
    "###################################################\n",
    "\n",
    "torch.manual_seed(RANDOM_SEED)\n",
    "model = MultilayerPerceptron(num_features=28*28,\n",
    "                             num_hidden=50,\n",
    "                             num_classes=10)\n",
    "\n",
    "minibatch_cost, epoch_cost = train(model, \n",
    "                                   train_loader,\n",
    "                                   num_epochs=NUM_EPOCHS,\n",
    "                                   learning_rate=0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(range(len(minibatch_cost)), minibatch_cost)\n",
    "plt.ylabel('Mean Squared Error')\n",
    "plt.xlabel('Minibatch')\n",
    "plt.show()\n",
    "\n",
    "plt.plot(range(len(epoch_cost)), epoch_cost)\n",
    "plt.ylabel('Mean Squared Error')\n",
    "plt.xlabel('Epoch')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training Accuracy: 94.72\n",
      "Test Accuracy: 94.49\n"
     ]
    }
   ],
   "source": [
    "def compute_accuracy(net, data_loader):\n",
    "    correct_pred, num_examples = 0, 0\n",
    "    with torch.no_grad():\n",
    "        for features, targets in data_loader:\n",
    "            features = features.view(-1, 28*28)\n",
    "            _, outputs = net.forward(features)\n",
    "            predicted_labels = torch.argmax(outputs, 1)\n",
    "            num_examples += targets.size(0)\n",
    "            correct_pred += (predicted_labels == targets).sum()\n",
    "        return correct_pred.float()/num_examples * 100\n",
    "    \n",
    "print('Training Accuracy: %.2f' % compute_accuracy(model, train_loader))\n",
    "print('Test Accuracy: %.2f' % compute_accuracy(model, test_loader))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visual Inspection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "for features, targets in test_loader:\n",
    "    break\n",
    "    \n",
    "fig, ax = plt.subplots(1, 4)\n",
    "for i in range(4):\n",
    "    ax[i].imshow(features[i].view(28, 28), cmap=matplotlib.cm.binary)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Predicted labels tensor([7, 2, 1, 0])\n"
     ]
    }
   ],
   "source": [
    "_, predictions = model.forward(features[:4].view(-1, 28*28))\n",
    "predictions = torch.argmax(predictions, dim=1)\n",
    "print('Predicted labels', predictions)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
